package com.intellij.ide.license.impl;

import com.intellij.ide.IdeBundle;
import com.intellij.ide.license.*;
import com.intellij.licensecommon.client.LicenseClientApplication;
import com.intellij.licensecommon.client.impl.ClientImpl;
import com.intellij.licensecommon.data.LicenseData;
import com.intellij.licensecommon.data.LicenseImpl;
import com.intellij.licensecommon.data.h;
import com.intellij.licensecommon.logging.LoggerFactoryHolder;
import com.intellij.licensecommon.message.a.ClientMessageFactoryImpl;
import com.intellij.licensecommon.net.Address;
import com.intellij.openapi.application.ApplicationAdapter;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.application.ex.ApplicationManagerEx;
import com.intellij.openapi.application.impl.ApplicationImpl;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.updateSettings.impl.UpdateChecker;
import org.jetbrains.rsa.RSAEncoder;

import javax.swing.*;
import java.awt.*;
import java.math.BigInteger;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.concurrent.atomic.AtomicBoolean;

public abstract class GeneralLicenseManager extends LicenseManager implements LicenseClientApplication {
    private static final Logger LOG = Logger.getInstance("#com.intellij.ide.license.impl.GeneralLicenseManager");
    private LicenseSource licenseSource;
    protected LicenseData licenseData;
    protected final ClientImpl clientImpl;
    protected LicenseFactory licenseFactory;
    protected LicenseSource[] licenseSources;
    private boolean h;
    private final AtomicBoolean i = new AtomicBoolean(false);

    public GeneralLicenseManager() {
        LoggerFactoryHolder.LOGGER_FACTORY = new LoggerFactoryImpl();
        this.clientImpl = createClient();
    }

    public LicenseSource getLicenseSource() {
        return this.licenseSource;
    }

    protected LicenseData getLicenseData() {
        return this.licenseData;
    }

    @Override
    public void startUp(StartupAction action) {
        boolean headless = GraphicsEnvironment.isHeadless();

        createLicenseFactory();
        a(this.licenseFactory);

        // 获取所有的 license
        for (LicenseSource source : get_LicenseSources()) {
            // 如果没有读取，则读取数据
            if (source.getLicenseData() == null) {
                source.c();
            }

            LicenseData licenseData = source.getLicenseData();
            if (licenseData != null) {
                // 验证
                Status status = validateLicense(action, source);

                // 如果不跳过
                if (status != Status.SKIP) {
                    UpdateChecker.addUpdateRequestParameter("license", getLicenseName(licenseData));
                    if (status != Status.OK) {
                        break;
                    }
                    int willExpire = (!headless) && (willExpire(licenseData, licenseData instanceof EvaluationLicense)) ? 1 : 0;
                    if (willExpire == 0) {
                        saveAndExecute(action, source, licenseData);
                        return;
                    }
                    break;
                }
            }
        }
        if (headless) {
            LOG.error("No valid license found");
            System.exit(-1);
        } else {
            askLicense(action);
        }
    }

    private static String getLicenseName(LicenseData licenseData) {
        if ((licenseData instanceof EvaluationLicense)) {
            return "eval";
        }
        StringBuilder buff = new StringBuilder();
        if ((licenseData instanceof ServerLicense)) {
            buff.append("server,");
        }
        if (licenseData.isClassroom()) {
            buff.append("classroom");
        } else if (licenseData.isPersonal()) {
            buff.append("personal");
        } else if (licenseData.isOpenSource()) {
            buff.append("opensource");
        } else if (licenseData.isAcademic()) {
            buff.append("academic");
        } else {
            buff.append("commercial");
        }
        return buff.toString();
    }

    private LicenseSource[] get_LicenseSources() {
        LicenseSource[] licenses = getLicenseSources();
        LicenseSource license = null;
        for (LicenseSource l : licenses) {
            try {
                l.c();
                if (l.getLicenseData() != null) {
                    l.b();
                }
            } catch (Exception localException) {
                continue;
            }
            license = l;
            break;
        }

        if (license != null) {
            ArrayList<LicenseSource> ls = new ArrayList<LicenseSource>(Arrays.asList(licenses));
            ls.remove(license);
            ls.add(0, license);
            return ls.toArray(new LicenseSource[ls.size()]);
        }
        return licenses;
    }

    @Override
    public void p() {
        if (((this.licenseData instanceof ServerLicense)) && ((this.licenseSource instanceof r))) {
            ((r) this.licenseSource).v();
            ((ServerLicense) this.licenseData).c(false);
        }
    }

    @Override
    public void n() {
        if (((this.licenseData instanceof ServerLicense)) && ((this.licenseSource instanceof r))) {
            ServerLicense localab = ((r) this.licenseSource).u();
            if (localab != null) {
                saveAndExecute(new p.a_() {
                    public void proceed() {
                    }

                    public void cancel() {
                    }
                }, this.licenseSource, localab);
            }
        }
    }

    protected void askLicense(StartupAction action) {
        showLicenseUpdateMessage(action, this.licenseSource);
    }

    public LicenseSource[] getLicenseSources() {
        return this.licenseSources;
    }


    protected boolean willExpire(LicenseData licenseData, boolean isEval) {
        if (licenseData == null) {
            return false;
        }
        Date expirationDate = licenseData.getExpirationDate();
        if (expirationDate == null) {
            return false;
        }

        long l1 = expirationDate.getTime() - System.currentTimeMillis();

        // 没过期，但小于7天
        if ((l1 >= 0L) && (l1 <= getDayMs(7))) {
            long l2 = l1 / getDayMs(1);
            return doGetLicenseFactory().getLicenseMessages().showWillExpireMessage(l2, isEval);
        }
        return false;
    }

    private static long getDayMs(int paramInt) {
        return paramInt * 24L * 60L * 60L * 1000L;
    }

    @Override
    protected GeneralLicenseManager.Status validateLicense(StartupAction action, LicenseSource source) {
        int isHeadless = !GraphicsEnvironment.isHeadless() ? 1 : 0;
        boolean bool1;
        try {
            source.checkValid();
        } catch (LicenseCorruptException e) {
            // license 冲突
            if (isHeadless != 0) {
                getLicenseMessages().b();
            } else {
                LOG.info(IdeBundle.message("message.license.is.corrupt", new Object[0]));
            }
            return Status.ASK;
        } catch (EvaluationLicenseExpiredException e) {
            // 评估 license 过期
            if (isHeadless != 0) {
                bool1 = getLicenseMessages().a();
                Status tmp130_127 = (bool1 ? Status.ASK : Status.OK);
                return tmp130_127;
            }
            LOG.info("Evaluation license expired");
            return Status.ASK;
        } catch (InvalidLicenseException e) {
            if (isHeadless != 0) {
                getLicenseMessages().c();
            } else {
                LOG.info(IdeBundle.message("message.invalid.license.data", new Object[0]));
            }
            return Status.ASK;
        } catch (ExpiredLicenseException e) {
            if (isHeadless != 0) {
                getLicenseMessages().h();
            } else {
                LOG.info(IdeBundle.message("message.license.expired", new Object[0]));
            }
            return Status.ASK;
        } catch (VersionNotMatchLicenseException localg) {
            if (isHeadless != 0) {
                getLicenseMessages().a(c(action, this.licenseSource));
            } else {
                LOG.info("The license is not valid for use with this version of the application");
            }
            return Status.ASK;
        } catch (LicenseException localb) {
            return Status.SKIP;
        }

        LicenseData locale1 = source.getLicenseData();
        if (locale1 == null) {
            return Status.SKIP;
        }

        if (!locale1.isAccepted()) {
            bool1 = isHeadless == 0;
            if ((bool1) || (!getLicenseMessages().a(locale1))) {
                if (bool1) {
                    LOG.info("A valid license found, but the license agreement is not read and accepted. Must be accepted in interactive mode.");
                }
                action.cancel();
                return Status.SKIP;
            }
            locale1.setAccepted(true);
            if ((locale1 instanceof EvaluationLicense)) {
                boolean bool2 = this.licenseFactory.saveEvaluationLicense((EvaluationLicense) locale1);
                if (!bool2) {
                    return Status.SKIP;
                }
            }
        }
        return Status.OK;
    }

    private void saveAndExecute(StartupAction action, LicenseSource source, LicenseData data) {
        LicenseSource orig = this.licenseSource;
        this.licenseSource = source;

        b(data);

        if ((source instanceof WritableLicense)) {
            try {
                ((WritableLicense) source).write(data);
            } catch (LicenseSaveException e) {
                LOG.error("License could not be saved due to following error:" + (e.getMessage() != null ? e.getMessage() : "NPE"), e);
                getLicenseMessages().a(e);
            }
        }
        if ((source.e()) && (!this.h)) {
            this.h = w();
        } else if ((!source.e()) && (this.h)) {
            this.h = (!x());
        }
        if (orig != source) {
            if ((orig instanceof ServerSource)) {
                ((ServerSource) orig).r();
            } else if ((orig instanceof p)) {
                ((p) orig).b(null);
            }
        }

        doAction(action);
    }

    private boolean w() {
        try {
            this.clientImpl.a(this);
            return true;
        } catch (com.intellij.licensecommon.net.b localb) {
            LOG.info("Network is already started.");
            return true;
        } catch (Exception localException) {
            LOG.info("Network startup failed.");
            if (LOG.isDebugEnabled()) {
                LOG.debug(localException);
            }
        }
        return false;
    }

    private boolean x() {
        try {
            this.clientImpl.g();
            return true;
        } catch (Exception localException) {
            LOG.info("Network shutDown failed.");
            if (LOG.isDebugEnabled()) {
                LOG.debug(localException);
            }
        }
        return false;
    }

    public void b(com.intellij.licensecommon.data.LicenseData parame) {
        this.licenseData = parame;
        System.setProperty("idea.registered", String.valueOf(!isEvaluationLicense()));
    }

    private void doAction(final StartupAction action) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                action.proceed();
                final LicenseData licenseData = GeneralLicenseManager.this.getLicenseData();

                SwingUtilities.invokeLater(new Runnable() {
                    public void run() {
                        if (licenseData.i()) {
                            GeneralLicenseManager.this.clientImpl.a(GeneralLicenseManager.toLicense(licenseData));

                            ApplicationManager.getApplication().addApplicationListener(new ApplicationAdapter() {
                                public void applicationExiting() {
                                    GeneralLicenseManager.this.clientImpl.f();
                                }
                            });
                        } else if (((licenseData instanceof ServerLicense)) && ((GeneralLicenseManager.this.licenseSource instanceof ServerSource))) {
                            ((ServerSource) GeneralLicenseManager.this.licenseSource).t();
                        }
                    }
                });
            }
        });
    }

    private static LicenseImpl toLicense(com.intellij.licensecommon.data.LicenseData licenseData) {
        if (licenseData instanceof JetProfileLicenseData) {
            JetProfileLicenseData jpld = (JetProfileLicenseData) licenseData;

            return new LicenseImpl(jpld.getUserId(), jpld.getLicense().getAssetId());
        }

        return LicenseImpl.toLicense(licenseData);
    }

    @Override
    protected void showLicenseUpdateMessage(StartupAction action, LicenseSource source) {
        LicenseMessages messages = getLicenseMessages();
        messages.b(isInvalid());
        messages.b(c(action, source));
    }

    private GeneralLicenseSource c(final StartupAction action, LicenseSource source) {

        return new AbstractLicenseSource(getLicenseSources(), source, doGetLicenseFactory()) {

            public void proceed(LicenseSource licenseSource) {

                if (licenseSource == null) {
                    throw new IllegalArgumentException(String.format("Argument %s for @NotNull parameter of %s.%s must not be null", new Object[]{"0", "com/intellij/ide/license/impl/GeneralLicenseManager$3", "proceed"}));
                }

                LicenseData licenseData = licenseSource.getLicenseData();

                Status status = GeneralLicenseManager.this.validateLicense(action, licenseSource);
                if (status == Status.OK) {
                    UpdateChecker.addUpdateRequestParameter("license", GeneralLicenseManager.getLicenseName(licenseData));

                    GeneralLicenseManager.this.saveAndExecute(action, licenseSource, licenseData);

                    super.a(licenseSource);

                    if (!(licenseSource instanceof EvaluationLicenseSource)) {
                        com.intellij.ide.license.ui.l.a(licenseData.getUsername());
                    }
                } else {
                    GeneralLicenseManager.this.showLicenseUpdateMessage(action, licenseSource);
                }
            }

            public void a() {
                action.cancel();
            }
        };
    }

    protected abstract LicenseMessages getLicenseMessages();

    @Override
    public boolean supportsRegistration() {
        return true;
    }

    /**
     * 显示注册
     */
    @Override
    public void register() {
        getLicenseMessages().a(true);
        getLicenseMessages().b(true);

        showLicenseUpdateMessage(new StartupAction() {
            public void proceed() {}

            public void cancel() {}
        }, getLicenseSource());
    }

    @Override
    public String licensedToMessage() {
        return IdeBundle.message("message.licensed.to", new Object[]{this.licenseData.getUsername()});
    }

    @Override
    public String licensedRestrictionsMessage() {
        return getLicenseMessages().b(this.licenseData);
    }

    private static ClientImpl createClient() {
        String time = Long.toString(System.currentTimeMillis());
        return new ClientImpl(new com.intellij.licensecommon.net.impl.c(new com.intellij.licensecommon.net.impl.d(), new com.intellij.licensecommon.net.impl.a(), new com.intellij.licensecommon.f.impl.a()), new ClientMessageFactoryImpl(time));
    }

    @Override
    public LicenseFactory doGetLicenseFactory() {
        if (this.licenseFactory == null) {
            createLicenseFactory();
        }
        return this.licenseFactory;
    }

    @Override
    public void a(LicenseFactory licenseFactory) {
        ArrayList<LicenseSource> localArrayList = new ArrayList();
        localArrayList.add(new o(licenseFactory));
        localArrayList.add(B());
        p localp = C();
        if (localp != null) {
            localArrayList.add(localp);
        }
        localArrayList.add(b(licenseFactory));
        this.licenseSources = localArrayList.toArray(new LicenseSource[localArrayList.size()]));
    }

    private EvaluationLicenseSource b(LicenseFactory paramo) {
        return new EvaluationLicenseSource(paramo, A());
    }

    protected long A() {
        return 30L;
    }

    @Override
    protected r B() {
        return new r(this.licenseFactory, this);
    }

    @Override
    protected abstract p C();

    @Override
    public boolean o() {
        return (this.licenseData != null) && (this.licenseData.willExpire());
    }

    public boolean isInvalid() {
        return (this.licenseData == null) || (this.licenseData.willExpire());
    }

    @Override
    public boolean isEvaluationLicense() {
        return this.licenseData instanceof EvaluationLicense;
    }

    @Override
    public Date getExpirationDate() {
        return this.licenseData.getExpirationDate();
    }

    @Override
    public boolean j() {
        return (isEvaluationLicense()) && (!isEAP());
    }

    @Override
    public boolean l() {
        return ((this.licenseData instanceof ServerLicense)) && (!((ServerLicense) this.licenseData).r());
    }

    @Override
    public boolean m() {
        return ((this.licenseData instanceof ServerLicense)) && (((ServerLicense) this.licenseData).r());
    }

    @Override
    public Date getUpgradeDueDate() {
        return (this.licenseData instanceof h) ? ((h) this.licenseData).getUpgradeDueDate() : null;
    }

    @Override
    public void a(Address address) {
        if (!this.licenseData.i()) {
            return;
        }
        com.intellij.licensecommon.net.impl.b localb = (com.intellij.licensecommon.net.impl.b) address;
        if (localb.isLoopback()) {
            return;
        }
        if (!this.i.getAndSet(true)) {
            final String str1 = a(a(localb));
            final String str2 = F();

            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    try {
                        boolean bool = GeneralLicenseManager.access$400() ? GeneralLicenseManager.a(str1, str2) : GeneralLicenseManager.b(str1, str2);
                        if (bool) {
                            GeneralLicenseManager.this.clientImpl.a(GeneralLicenseManager.toLicense(GeneralLicenseManager.this.getLicenseData()));
                        } else {
                            GeneralLicenseManager.exit();
                        }
                    } finally {
                        GeneralLicenseManager.this.i.set(false);
                    }
                }
            });
        }
    }

    private static String a(com.intellij.licensecommon.net.impl.b paramb) {
        InetAddress address = paramb.getInetAddress();
        return address.getHostName() + " (" + address.getHostAddress() + ")";
    }

    private static boolean a(String title, String message) {
        int m = JOptionPane.showConfirmDialog(JOptionPane.getRootFrame(), title, message, 0, 0);
        return m == 0;
    }

    private static boolean b(String title, String message) {
        int m = Messages.showYesNoDialog(title, message, Messages.getErrorIcon());
        return m == 0;
    }

    private static String F() {
        return IdeBundle.message("title.license.collision.detected", new Object[0]);
    }

    private static String a(String paramString) {
        return IdeBundle.message("error.license.collision", new Object[]{paramString, ApplicationNamesInfo.getInstance().getProductName()});
    }

    static void exit() {
        if (hasApp()) {
            exitSystem();
        } else {
            extApp();
        }
    }

    private static boolean hasApp() {
        return ApplicationManagerEx.getApplicationEx() == null;
    }

    private static void exitSystem() {
        System.exit(-1);
    }

    private static void extApp() {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                ((ApplicationImpl) ApplicationManagerEx.getApplicationEx()).exit(true, false, false);
            }
        });
    }

    private static BigInteger EXP = new BigInteger("ba3da866372947f737c0120610ae281f1085659726cbd2b1288ac7a2b95acef7392d4c848d4cab7767c2c972bdf4e4f73482ef23fb31bf6dda4cbcbf82924d97", 16);
    private static BigInteger MOD = new BigInteger("395af9bc98ea4eae74ede2df194df92f2ff0550c0ab7a4a8487b0ce6313d25157905b0b480f3e13b86a06e69b120ee687bbca0b93f6c512241261862a5d76f89", 16);

    public String encode(BigInteger paramBigInteger) {
        RSAEncoder localRSAEncoder = new RSAEncoder(MOD, EXP);
        return localRSAEncoder.encode(paramBigInteger.toByteArray());
    }

    public static enum Status {
        SKIP, ASK, OK
    }
}
